package com.lingshu.app.service;

import com.lingshu.app.network.RetrofitMobileClient;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;

import cn.hutool.core.io.FileUtil;
import io.reactivex.Observable;
import io.reactivex.schedulers.Schedulers;
import okhttp3.ResponseBody;
import retrofit2.Response;

/**
 * @author 于定金
 * @version 1.0
 * @Date 2024/4/9 10:18
 * @Description
 */
public class DownloadManager {
    private static final String TAG = DownloadManager.class.getName();

    public Observable<String> downloadImage(long imageId, String savePath) {
        return handlerImage(imageId).flatMap(responseBodyResponse -> {
            return saveFile(responseBodyResponse, savePath);
        }).flatMap(file -> {
            return unzipFile(file);
        }).subscribeOn(Schedulers.io());
    }

    public Observable<File> downloadScreenshot(long id, String savePath) {
        return downloadFile(id).flatMap(response -> {
            return saveFile(response, savePath);
        }).subscribeOn(Schedulers.io());
    }

    private Observable<Response<ResponseBody>> downloadFile(long id) {
        return RetrofitMobileClient.getInstance().getService(DownloadService.class).downloadScreenshot(id).subscribeOn(Schedulers.io());
    }

    private Observable<Response<ResponseBody>> handlerImage(long imageId) {
        return RetrofitMobileClient.getInstance().getService(DownloadService.class).downloadImage(imageId).subscribeOn(Schedulers.io());
    }

    private Observable<File> saveFile(Response<ResponseBody> response, String savePath) {
        return Observable.create(emitter -> {
            File destinationFile = new File(savePath);
            File directory = new File(destinationFile.getParent());
            if (!directory.exists()) directory.mkdirs();
            FileUtil.writeFromStream(response.body().byteStream(), destinationFile);
            emitter.onNext(destinationFile);
            emitter.onComplete();
        });
    }

    private Observable<String> unzipFile(File zipFile) {
        return Observable.create(emitter -> {
            try {
                String destinationPath = zipFile.getAbsolutePath().replace(".zip", "");
                File outDirectory = new File(destinationPath);
                if (!outDirectory.exists()) {
                    outDirectory.mkdirs();
                }
                FileInputStream fileInput = new FileInputStream(zipFile);
                ZipInputStream zipInput = new ZipInputStream(new BufferedInputStream(fileInput));
                byte[] buffer = new byte[1024];
                ZipEntry entry;
                while ((entry = zipInput.getNextEntry()) != null) {
                    String entryName = entry.getName();
                    String filePath = destinationPath + File.separator + entryName;

                    if (entry.isDirectory()) {
                        File dir = new File(filePath);
                        dir.mkdirs();
                    } else {
                        FileOutputStream output = new FileOutputStream(filePath);
                        BufferedOutputStream dest = new BufferedOutputStream(output, 1024);

                        int count;
                        while ((count = zipInput.read(buffer, 0, 1024)) != -1) {
                            dest.write(buffer, 0, count);
                        }
                        dest.flush();
                        dest.close();
                    }
                }
                zipInput.close();
                //最后删除压缩文件
                zipFile.delete();
                emitter.onNext(destinationPath + "/0.jpeg");
                emitter.onComplete();
            } catch (IOException e) {
                emitter.onError(e);
            }
        });
    }
}
